package cn.milolab.djback.conf.requestprocessor;

import cn.milolab.djback.annotation.DJRoleCheck;
import cn.milolab.djback.bean.entity.Employee;
import cn.milolab.djback.bean.entity.User;
import cn.milolab.djback.conf.DjException;
import cn.milolab.djback.conf.jwt.JwtUtil;
import cn.milolab.djback.dao.EmployeeDAO;
import cn.milolab.djback.dao.UserDAO;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * @author 叶欣委
 */
@Slf4j
@Component
public class TokenValidationInterceptor extends HandlerInterceptorAdapter {

    @Autowired
    UserDAO userDAO;
    @Autowired
    EmployeeDAO employeeDAO;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        request.setAttribute("userId",2);
        if(!(handler instanceof HandlerMethod)){
            return false;
        }

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        //获取到控制层的方法
        Method method = handlerMethod.getMethod();

        // 获取请求handler上标注的DjRoleCheck注解
        DJRoleCheck djRoleCheckAnnotation = method.getAnnotation(DJRoleCheck.class);

        if (djRoleCheckAnnotation == null) {
            // 如果rest controller的handler上没有标注@DJRoleCheck，报警
            log.warn("警告：未鉴权的REST API调用: " + handler.toString());
            return true;
        }
        // 获取调用这个接口需要的权限级别
        Employee.RoleLevel targetRoleLevel = djRoleCheckAnnotation.value();

        // 如果未登录就可以使用这个接口，则直接放行
        if (targetRoleLevel == Employee.RoleLevel.UNREGISTERED) {
            return true;
        }

        //从请求头中尝试获取token
        String token = request.getHeader("Authorization");
        //从请求参数中尝试获取token
        if (StringUtils.isEmpty(token)) {
            token = request.getParameter("Authorization");
        }
        if (StringUtils.isEmpty(token)) {
            throw DjException.accessDenied("未登录");
        }

        //检验token
        Claims claims = JwtUtil.parseToken(token);
        if (StringUtils.isEmpty(claims)) {
            throw DjException.accessDenied("验证失效，请重新登录");
        }
        Integer userId = (Integer) claims.get("userId");

        // 如果需要更高级的权限，但没有userId，也就是未登录，不通过
        if (StringUtils.isEmpty(userId)) {
            throw DjException.accessDenied("未登录");
        } else {
            if (userId instanceof Integer) {
                //将userId放入请求参数中
                request.setAttribute("userId",userId);

                User user = userDAO.getUserById(1);
//                User user = userDAO.getUserById(userId);

                //UNREGISTERED以上的权限都需要用户实体，若没有，则拦截
                if (StringUtils.isEmpty(user)) {
                    throw DjException.accessDenied("用户数据未找到");
                }

                if (targetRoleLevel == Employee.RoleLevel.COMMON_WECHAT_USER) {
                    return true;
                }

                Employee employee = employeeDAO.getEmployeeByUserId(user.getId());

                // COMMON_WECHAT_USER以上的权限都需要社员实体，若没有，则拦截
                if (StringUtils.isEmpty(employee)) {
                    throw DjException.accessDenied("社员数据未找到");
                }

                Employee.RoleLevel requestRoleLevel = employee.getRole();

                // 如果社员权限大于需要权限，则放行
                if(requestRoleLevel.getLevel() >= targetRoleLevel.getLevel()){
                    return true;
                }else {
                    throw DjException.accessDenied("权限不足");
                }
            } else {
                // 如果userId不是整形
                throw new RuntimeException("非法参数");
            }
        }

    }

}
